﻿namespace DomainServices.Tools.Pdb.SymStore
{
    using System;
    using System.Diagnostics.SymbolStore;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;

    internal class SymbolBinder : ISymbolBinder1, ISymbolBinder2
    {
        protected static readonly Guid CLSID_CorSymBinder = new Guid("0A29FF9E-7F9C-4437-8B11-F424491E3931");
        private ISymUnmanagedBinder m_binder;

        public SymbolBinder()
        {
            object obj2 = (ISymUnmanagedBinder) Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_CorSymBinder));
            this.m_binder = (ISymUnmanagedBinder) obj2;
        }

        internal SymbolBinder(ISymUnmanagedBinder comBinderObject)
        {
            if (comBinderObject == null)
            {
                throw new ArgumentNullException("comBinderObject");
            }
            this.m_binder = comBinderObject;
        }

        public ISymbolReader GetReader(IntPtr importer, string filename, string searchPath)
        {
            ISymUnmanagedReader retVal = null;
            int hr = this.m_binder.GetReaderForFile(importer, filename, searchPath, out retVal);
            if (IsFailingResultNormal(hr))
            {
                return null;
            }
            Marshal.ThrowExceptionForHR(hr);
            return new SymReader(retVal);
        }

        public ISymbolReader GetReaderForFile(object importer, string filename, string searchPath)
        {
            ISymUnmanagedReader retVal = null;
            IntPtr zero = IntPtr.Zero;
            try
            {
                zero = Marshal.GetIUnknownForObject(importer);
                int hr = this.m_binder.GetReaderForFile(zero, filename, searchPath, out retVal);
                if (IsFailingResultNormal(hr))
                {
                    return null;
                }
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.Release(zero);
                }
            }
            return new SymReader(retVal);
        }

        public ISymbolReader GetReaderForFile(object importer, string fileName, string searchPath, SymSearchPolicies searchPolicy)
        {
            ISymUnmanagedReader pRetVal = null;
            IntPtr zero = IntPtr.Zero;
            try
            {
                zero = Marshal.GetIUnknownForObject(importer);
                int hr = ((ISymUnmanagedBinder2) this.m_binder).GetReaderForFile2(zero, fileName, searchPath, (int) searchPolicy, out pRetVal);
                if (IsFailingResultNormal(hr))
                {
                    return null;
                }
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.Release(zero);
                }
            }
            return new SymReader(pRetVal);
        }

        public ISymbolReader GetReaderForFile(object importer, string fileName, string searchPath, SymSearchPolicies searchPolicy, object callback)
        {
            ISymUnmanagedReader pRetVal = null;
            IntPtr zero = IntPtr.Zero;
            try
            {
                zero = Marshal.GetIUnknownForObject(importer);
                int hr = ((ISymUnmanagedBinder3) this.m_binder).GetReaderFromCallback(zero, fileName, searchPath, (int) searchPolicy, callback, out pRetVal);
                if (IsFailingResultNormal(hr))
                {
                    return null;
                }
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.Release(zero);
                }
            }
            return new SymReader(pRetVal);
        }

        public static ISymbolReader GetReaderFromCOM(object reader)
        {
            return new SymReader((ISymUnmanagedReader) reader);
        }

        public ISymbolReader GetReaderFromStream(object importer, IStream stream)
        {
            ISymUnmanagedReader retVal = null;
            IntPtr zero = IntPtr.Zero;
            try
            {
                zero = Marshal.GetIUnknownForObject(importer);
                int hr = ((ISymUnmanagedBinder2) this.m_binder).GetReaderFromStream(zero, stream, out retVal);
                if (IsFailingResultNormal(hr))
                {
                    return null;
                }
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.Release(zero);
                }
            }
            return new SymReader(retVal);
        }

        private static bool IsFailingResultNormal(int hr)
        {
            return (hr == -2140340219);
        }
    }
}

